package epoch.game.core.thread;

import java.util.Collection;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.lang3.time.StopWatch;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import epoch.game.core.action.IAction;
import epoch.game.core.distr.Node;
import epoch.game.core.distr.ThreadContext;
import epoch.game.core.timer.GameTimer;
import epoch.game.core.timer.ServerTimerTask;

/**
 * 服务器线程
 * 
 * @author Administrator
 *
 */
public class ServerThread extends Thread {

	private Logger log = null;

	/**
	 * 等待执行的命令队列（优先级高）
	 */
	private LinkedBlockingQueue<IAction> actionQueue = new LinkedBlockingQueue<IAction>();
	/**
	 * 可以后台执行的命令队列(优先级低)
	 */
	private LinkedBlockingQueue<IAction> timerActionQueue = new LinkedBlockingQueue<IAction>();
	//运行类型是否开启sleep-run模式
	private boolean sleepRunMode = true;
	// 心跳间隔
	private int heart = 0;
	// 线程名称
	private String threadName;
	// 执行完之后固定间隔的定时任务
	private ServerTimerTask timerTask;
	// 运行状态
	private volatile boolean running = false;
	// 匿名线程序号
	private static AtomicLong threadSeqNum = new AtomicLong(1);
	// 线程数据
	private ThreadContext context;
	// 
	private StopWatch watch;

	public ServerThread() {		
		this("ServerThread-"+threadSeqNum.getAndAdd(1L));
	}

	/**
	 * 服务器线程构造器
	 * 
	 * @param threadName
	 *            线程名称
	 */
	public ServerThread(String threadName) {
		this(threadName, 50);
	}

	/**
	 * 服务器线程构造器
	 * 
	 * @param threadGroup
	 * @param threadName
	 */
	public ServerThread(ThreadGroup threadGroup, String threadName) {
		this(threadGroup, threadName, 50);
	}

	/**
	 * 服务器线程构造器
	 * 
	 * @param threadName
	 *            线程名称
	 * @param heart
	 *            心跳间隔
	 */
	public ServerThread(String threadName, int heart) {
		super(threadName);
		this.threadName = threadName;
		this.heart = heart;
		log = LogManager.getLogger(this.threadName);
		if (this.heart <= 0) {
			log.info("thread:"+"threadName"+" \"heart\" is smaller than 0.");
		}else{
			timerTask = new ServerTimerTask(this);
		}
		initContext();
		setExceptionHandler();
	}

	/**
	 * 服务器线程构造器
	 * 
	 * @param threadGroup
	 * @param threadName
	 * @param heart
	 */
	public ServerThread(ThreadGroup threadGroup, String threadName, int heart) {
		super(threadGroup, threadName);
		this.threadName = threadName;
		this.heart = heart;
		log = LogManager.getLogger(this.threadName);
		if (this.heart <= 0) {
			log.info("thread:"+"threadName"+" \"heart\" is smaller than 0.");
		}else{
			timerTask = new ServerTimerTask(this);
		}
		initContext();
		setExceptionHandler();
	}
	
	/**
	 * 构建服务器线程，没有定时器功能
	 * @param threadGroup
	 * @param target
	 * @param threadName
	 * @param stackSize
	 */
	public ServerThread(ThreadGroup threadGroup,Runnable target, String threadName,long stackSize){
		super(threadGroup, target, threadName,stackSize);
		this.threadName = threadName;
		initContext();
		setExceptionHandler();
	}
	
	/**
	 * 设置线程异常处理
	 */
	private void setExceptionHandler() {
		setUncaughtExceptionHandler((thread, throwable) -> {
			log.error("server thread uncaughtException:"+throwable, throwable);
			if (timerTask != null) {
				timerTask.cancel(true);
			}
			actionQueue.clear();
			timerActionQueue.clear();
		});
	}
	
	/**
	 * 初始化线程数据上下文
	 */
	protected void initContext(){
		if(sleepRunMode && watch==null){
			watch = new StopWatch();
		}
		ThreadContext current = ThreadContext.getCurrent();
		if (current != null) {
			Node node = current.getNode();
			if (node != null) {
				this.setContext(new ThreadContext(node, this));
			}
		}
	}

	public ThreadContext getContext() {
		return context;
	}

	public void setContext(ThreadContext context) {
		if (running) {
			//启动后不能再设置线程数据，只能在启动前绑定
			throw new IllegalStateException(this.threadName + " is running, can not set context now!");
		}
		this.context = context;
	}
	
	

	public boolean isSleepRunMode() {
		return sleepRunMode;
	}

	public void setSleepRunMode(boolean sleepRunMode) {
		if (running) {
			//启动后不能再设置线程数据，只能在启动前绑定
			throw new IllegalStateException(this.threadName + " is running, can not set sleepRunMode now!");
		}
		this.sleepRunMode = sleepRunMode;
		if(sleepRunMode && watch==null){
			watch = new StopWatch();
		}
	}

	@Override
	public void start() {
		if (!running) {
			running = true;
			super.start();
			if (timerTask != null) {
				timerTask.start();
			}
		}		
	}

	@Override
	public void run() {
		if(context!=null){
			context.onThreadStart();
		}
		try{
			super.run();
		}catch(Throwable ex){
			log.error("server thread do super.run() occured error!", ex);
		}
		if(sleepRunMode){
			doSleepRun();
		}else{
			doWaitNotifyRun();
		}
		if (timerTask != null) {
			timerTask.cancel(true);
		}
		if(context!=null){
			context.onThreadStop();
			this.context = null;
		}
	}
	
	/**
	 * wait-notify模式运行
	 */
	private void doWaitNotifyRun(){
		while (running) {
			try {
				// TODO:will@优先执行优先级高的,但是应该处理一定量之后要处理部分优先级较低的任务
				IAction action = actionQueue.poll();
				if (action != null) {
					try {
						action.action();
					} catch (Exception ex) {
						log.error("server thread action error!", ex);
					}
					continue;
				}
				action = timerActionQueue.poll();
				if (action != null) {
					try {
						action.action();
					} catch (Exception ex) {
						log.error("server thread timeraction error!", ex);
					}
					continue;
				}
				synchronized (this) {
					wait();
				}
			} catch (Throwable ex) {
				log.error("server thread occured error!", ex);
			}
		}
	}
	
	/**
	 * sleep-run模式运行
	 */
	public void doSleepRun(){
		while (running) {
            try {
                IAction action = actionQueue.poll();
                if (action != null) {
                    action.action();
                } else {
                    Thread.sleep(1);
                }
            } catch (Throwable ex) {
                log.error("server thread occured error!", ex);
            }
            /*
			try {
				// 开始处理
				watch.start();
				// 获取本次需要执行的任务
				List<IAction> actions = new LinkedList<>();
				IAction action = actionQueue.poll();
				while (action != null) {
					actions.add(action);
					action = actionQueue.poll();
				}
				for (IAction act : actions) {
					try {
						act.action();
					} catch (Exception ex) {
						log.error("server thread action error!", ex);
					}
				}
				watch.stop();
				long timeRunning = watch.getTime();
				// 尽量保证心跳帧率 每次执行后至少休息1毫秒 避免极端情况下连续执行占用过多系统资源
				if (timeRunning < heart) {
					Thread.sleep(heart - timeRunning);
				} else {
					Thread.sleep(1);
				}
			} catch (Throwable ex) {
				log.error("server thread occured error!", ex);
			} finally {
				watch.reset();
			}
            */
		}
	}

	/**
	 * 心跳间隔（ms)
	 * 
	 * @return
	 */
	public int getHeart() {
		return heart;
	}

	/**
	 * 判断服务器线程是否已经停止
	 * 
	 * @return
	 */
	public boolean isStoped() {
		return !running;
	}

	/**
	 * 停止服务器线程
	 * 
	 * @param force
	 *            是否强制停止，为true时会立即中段线程的执行，为false则不会再接受任务，直到当前任务执行完之后停止线程
	 */
	public void stop(boolean force) {
		if (force) {
			stopNow();
		} else {
			running = false;
			if (timerTask != null) {
				timerTask.cancel(false);
			}
			synchronized (this) {
				notify();
			}
		}
	}

	/**
	 * 停止任务的执行
	 */
	private void stopNow() {
		running = false;
		if (timerTask != null) {
			timerTask.cancel(true);
		}
		this.interrupt();
		actionQueue.clear();
		synchronized (this) {
			notify();
		}
	}
	
	public boolean hasActions(){
		return actionQueue.size()>0;
	}

	/**
	 * 添加任务
	 * 
	 * @param action
	 */
	public void addAction(IAction action) {
		if(!running){
			throw new IllegalStateException(this.threadName + " is not running");
		}
		try{			
			actionQueue.add(action);
			if (!sleepRunMode) {
				synchronized (this) {
					notify();
				}
			}
		}catch(Exception ex){
			log.error("server thread addAction err: action="+action+",ex="+ex,ex);
			if (!sleepRunMode) {
				synchronized (this) {
					notify();
				}
			}
			throw ex;
		}
	}

	/**
	 * 添加任务的集合
	 * 
	 * @param actions
	 */
	public void addActions(Collection<IAction> actions) {
		if(!running){
			throw new IllegalStateException(this.threadName + " is not running");
		}
		actionQueue.addAll(actions);
		if (!sleepRunMode) {
			synchronized (this) {
				notify();
			}
		}
	}

	/**
	 * 添加定时器任务
	 * 
	 * @param action
	 */
	public void addTimerAction(IAction action) {
		if (!running) {
			throw new IllegalStateException(this.threadName + " is not running");
		}
		timerActionQueue.add(action);
		if (!sleepRunMode) {
			synchronized (this) {
				notify();
			}
		}
	}

	/**
	 * 添加定时器任务的集合
	 * 
	 * @param actions
	 */
	public void addTimerActions(Collection<IAction> actions) {
		if (!running) {
			throw new IllegalStateException(this.threadName + " is not running");
		}
		timerActionQueue.addAll(actions);
		if (!sleepRunMode) {
			synchronized (this) {
				notify();
			}
		}
	}

	/**
	 * 注册定时器
	 * 
	 * @param timer
	 */
	public void registerTimer(GameTimer timer) {
		if (this.timerTask != null) {
			this.timerTask.addTimer(timer);
		}
	}
	
	/**
	 * 取消定时器
	 * 
	 * @param timer
	 */
	public void removeTimer(GameTimer timer) {
		if (this.timerTask != null) {
			this.timerTask.removeTimer(timer);
		}
	}
	
	/**
	 * 开始执行timer
	 */
	public void startTimer(){
		if(timerTask != null){
			timerTask.start();
		}
	}
	
	/**
	 * 停止timer的执行
	 */
	public void stopTimer(){
		if (timerTask != null) {
			timerTask.cancel(false);
		}
	}

	
}
